package com.bookmall.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bookmall.common.constant.DefaultDataConstants;
import com.bookmall.common.constant.ExceptionTypeConstants;
import com.bookmall.common.constant.MyStatusConstants;
import com.bookmall.common.entity.to.MemberInfoTo;
import com.bookmall.common.enume.OrderStatusEnum;
import com.bookmall.common.exception.LoginException;
import com.bookmall.common.utils.HttpUtils;
import com.bookmall.member.domain.MemberInfo;
import com.bookmall.member.domain.MemberLevel;
import com.bookmall.member.domain.vo.*;
import com.bookmall.member.feign.OrderFeignService;
import com.bookmall.member.interceptor.MemberInterceptor;
import com.bookmall.member.mapper.MemberInfoMapper;
import com.bookmall.member.mapper.MemberLevelMapper;
import com.bookmall.member.service.IMemberInfoService;
import com.bookmall.member.service.IMemberLevelService;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotBlank;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author 胡菜鸡
 * @Create 2022-04-01-9:51
 */
@Service
public class MemberInfoServiceImpl extends ServiceImpl<MemberInfoMapper, MemberInfo> implements IMemberInfoService {
    @Autowired
    private MemberInfoMapper memberInfoMapper;

    @Autowired
    private MemberLevelMapper memberLevelMapper;

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private IMemberLevelService memberLevelService;

    /**
     * 会员注册（向数据库中保存一条会员信息）
     * @author 胡菜鸡
     * @date 2022/4/2 16:49
     */
    @Override
    public int register(RegisterUserVo registerUserVo) throws LoginException {
        //如果学号或者手机号已存在，则抛出异常
        if(checkStuIdUniques(registerUserVo.getStuId())){
            throw new LoginException("此学号已存在", ExceptionTypeConstants.STUDENT_ID_EXIST);
        }
        if(checkPhoneUniques(registerUserVo.getPhone())){
            throw new LoginException("此手机号已存在", ExceptionTypeConstants.PHONE_EXIST);
        }
        //设置用户基本数据
        MemberInfo memberInfo = new MemberInfo();
        memberInfo.setStuId(registerUserVo.getStuId());
        memberInfo.setNickname(registerUserVo.getNickname());
        memberInfo.setPhone(registerUserVo.getPhone());
        memberInfo.setSex(registerUserVo.getSex());
        memberInfo.setIcon(DefaultDataConstants.DEFAULT_USER_ICON);
        memberInfo.setSign(DefaultDataConstants.DEFAULT_USER_SIGN);
        memberInfo.setRegisterTime(DateUtils.getNowDate());
        //如果存在默认等级，则赋给新用户以默认等级
        LambdaQueryWrapper<MemberLevel> wrapper = new LambdaQueryWrapper<>();
        MemberLevel memberLevel = memberLevelMapper.selectOne(wrapper.eq(MemberLevel::getDefaultStatus, MyStatusConstants.DEFAULT));
        if(memberLevel != null){
            memberInfo.setMemberLevelId(memberLevel.getId());
        }
        //设置用户密码（MD5盐值加密）
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(registerUserVo.getPassword());  //加密
        memberInfo.setPassword(encode);

        return memberInfoMapper.insert(memberInfo);
    }

    /**
     * 会员登录
     * @author 胡菜鸡
     * @date 2022/4/3 16:46
     */
    @Override
    public MemberInfo login(LoginUserVo loginUserVo) throws LoginException {
        String username = loginUserVo.getUsername();
        String password = loginUserVo.getPassword();

        //从数据库查询数据（用户名、学号、手机号满足其一即可）
        LambdaQueryWrapper<MemberInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MemberInfo::getUsername, username)
                .or().eq(MemberInfo::getStuId, username)
                .or().eq(MemberInfo::getPhone, username);
        List<MemberInfo> memberInfoList = memberInfoMapper.selectList(wrapper);

        //数据校验
        if(memberInfoList == null || memberInfoList.size() == 0){
            throw new LoginException("账号不存在", ExceptionTypeConstants.ACCOUNT_NOT_EXIST);
        }

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //如果只查到了一个会员数据
        if(memberInfoList.size() == 1){
            MemberInfo account = memberInfoList.get(0);
            //直接校验密码
            if(passwordEncoder.matches(password, account.getPassword())){
                return account;
            }
        }
        //如果查到了多个会员数据
        else if(memberInfoList.size() > 1){
            //依次校验
            for (MemberInfo account : memberInfoList) {
                if(passwordEncoder.matches(password, account.getPassword())){
                    return account;
                }
            }
        }
        throw new LoginException("密码错误", ExceptionTypeConstants.PASSWORD_ERROR);
    }

    /**
     * 社交登录
     * @author 胡菜鸡
     * @date 2022/4/4 19:28
     */
    @Override
    public MemberInfo login(SocialUser socialUser) throws LoginException {
        String uid = socialUser.getUid();
        //1.判断当前社交用户是否登录过系统
        LambdaQueryWrapper<MemberInfo> wrapper = new LambdaQueryWrapper<>();
        MemberInfo memberInfo = memberInfoMapper.selectOne(wrapper.eq(MemberInfo::getSocialUid, uid));
        if (memberInfo != null) {
            //2、这个用户已经注册
            MemberInfo loginEntity = new MemberInfo();
            loginEntity.setId(memberInfo.getId());
            loginEntity.setAccessToken(socialUser.getAccessToken());
            loginEntity.setExpiresIn(socialUser.getExpiresIn());

            //3、修改这个用户的令牌和过期时间
            memberInfoMapper.updateById(loginEntity);

            //4、将新的登录数据返回
            memberInfo.setAccessToken(socialUser.getAccessToken());
            memberInfo.setExpiresIn(socialUser.getExpiresIn());
            return memberInfo;
        } else {
            //2、该用户没有注册（第一次登录），则进行注册
            MemberInfo registerEntity = new MemberInfo();
            try {
                //3、查询当前社交账号的基本信息
                Map<String, String> map = new HashMap<>();
                map.put("access_token", socialUser.getAccessToken());
                map.put("uid", socialUser.getUid());
                HttpResponse response = HttpUtils.doGet(
                        "https://api.weibo.com",
                        "/2/users/show.json",
                        "get", new HashMap<>(), map);

                if (response.getStatusLine().getStatusCode() == 200) {
                    //查询成功
                    String json = EntityUtils.toString(response.getEntity());
                    JSONObject jsonObject = JSON.parseObject(json);

                    //4、将社交账号的基本信息赋值给新账号
                    registerEntity.setNickname(jsonObject.getString("screen_name"));   //昵称
                    if("m".equalsIgnoreCase(jsonObject.getString("gender"))){
                        registerEntity.setSex("男");
                    } else if("f".equalsIgnoreCase(jsonObject.getString("gender"))){
                        registerEntity.setSex("女");
                    } else {
                        registerEntity.setSex("未知");
                    }
                    registerEntity.setSign(jsonObject.getString("description"));
                    registerEntity.setIcon(jsonObject.getString("avatar_hd"));
                    registerEntity.setUsername(jsonObject.getString("weihao"));
                    String[] location = jsonObject.getString("location").split(" ");
                    if(location.length > 0){
                        registerEntity.setProvince(location[0]);
                        if(location.length > 1){
                            registerEntity.setCity(location[1]);
                        }
                    }
                    //......
                }
            } catch (Exception e) { }
            //5、设置新账号的社交登录信息
            registerEntity.setSocialUid(socialUser.getUid());
            registerEntity.setAccessToken(socialUser.getAccessToken());
            registerEntity.setExpiresIn(socialUser.getExpiresIn());
            registerEntity.setRegisterTime(DateUtils.getNowDate());
            //如果存在默认等级，则赋给新用户以默认等级
            MemberLevel memberLevel = memberLevelMapper.selectOne(new LambdaQueryWrapper<MemberLevel>()
                    .eq(MemberLevel::getDefaultStatus, MyStatusConstants.DEFAULT));
            if(memberLevel != null){
                registerEntity.setMemberLevelId(memberLevel.getId());
            }

            //6、保存新的社交登录账号
            memberInfoMapper.insert(registerEntity);
            return registerEntity;
        }
    }

    /**
     * 检查学号是否存在
     * @author 胡菜鸡
     * @date 2022/4/2 17:18
     * @return true为存在
     */
    @Override
    public boolean checkStuIdUniques(String stuId) {
        LambdaQueryWrapper<MemberInfo> wrapper = new LambdaQueryWrapper<>();
        Long count = memberInfoMapper.selectCount(wrapper.eq(MemberInfo::getStuId, stuId));
        return count > 0;
    }

    /**
     * 检查手机号是否存在
     * @author 胡菜鸡
     * @date 2022/4/2 17:18
     * @return true为存在
     */
    @Override
    public boolean checkPhoneUniques(String phone) {
        LambdaQueryWrapper<MemberInfo> wrapper = new LambdaQueryWrapper<>();
        Long count = memberInfoMapper.selectCount(wrapper.eq(MemberInfo::getPhone, phone));
        return count > 0;
    }

    /**
     * 检查用户名是否存在
     * @author 胡菜鸡
     * @date 2022/4/2 17:18
     * @return true为存在
     */
    @Override
    public boolean checkUsernameUniques(String username) {
        LambdaQueryWrapper<MemberInfo> wrapper = new LambdaQueryWrapper<>();
        Long count = memberInfoMapper.selectCount(wrapper.eq(MemberInfo::getUsername, username));
        return count > 0;
    }

    /**
     * 通过学生学号查询会员详细信息
     * @author 胡菜鸡
     * @date 2022/4/8 17:36
     */
    @Override
    public MemberInfo selectMemberInfoByStuId(String stuId) {
        LambdaQueryWrapper<MemberInfo> wrapper = new LambdaQueryWrapper<>();
        MemberInfo memberInfo = memberInfoMapper.selectOne(wrapper.eq(MemberInfo::getStuId, stuId));
        return memberInfo;
    }

    /**
     * 获取个人账户相关信息
     * @author 胡菜鸡
     * @date 2022/4/27 15:44
     */
    @Override
    public PersonInfoVo getPersonInfo(PersonParamVo personParamVo) {
        PersonInfoVo personInfoVo = new PersonInfoVo();
        //0、拼接原本的查询条件
        String timeStr = "全部订单";
        if(personParamVo.getCreateTime() != null){
            switch (personParamVo.getCreateTime()) {
                case 1: timeStr = "近一个月订单"; break;
                case 3: timeStr = "近三个月订单"; break;
                case 6: timeStr = "半年内订单"; break;
                case 12: timeStr = "一年内订单"; break;
                case -12: timeStr = "一年前订单"; break;
            }
        }
        personParamVo.setCreateTimeChina(timeStr);
        if(personParamVo.getStatus() != null && personParamVo.getStatus() != -1){
            personParamVo.setStatusChina(OrderStatusEnum.getByCode(personParamVo.getStatus()));
        } else {
            personParamVo.setStatusChina("全部状态");
        }
        personInfoVo.setParam(personParamVo);

        //1、获取个人所有订单以及订单项
        personInfoVo.setOrderPage(getMemberOrders(personParamVo));

        return personInfoVo;
    }

    /**
     * 保存一个用户
     * @author 胡菜鸡
     * @date 2022/5/6 13:43
     */
    @Override
    public int saveMember(MemberInfo memberInfo) {
        if(memberInfo.getNickname() == null || memberInfo.getStuId() == null || memberInfo.getPassword() == null || memberInfo.getPhone() == null){
            throw new ServiceException("缺少部分数据没有传入，请检查传入数据");
        }
        //如果学号或者手机号已存在，则抛出异常
        if(checkStuIdUniques(memberInfo.getStuId())){
            throw new LoginException("此学号已存在", ExceptionTypeConstants.STUDENT_ID_EXIST);
        }
        if(checkPhoneUniques(memberInfo.getPhone())){
            throw new LoginException("此手机号已存在", ExceptionTypeConstants.PHONE_EXIST);
        }
        //设置默认数据
        memberInfo.setMemberLevel(1L);
        MemberLevel defaultLevel = memberLevelService.getDefaultLevel();
        memberInfo.setMemberLevelId(defaultLevel.getId());
        if(StringUtils.isBlank(memberInfo.getIcon())){
            memberInfo.setIcon(DefaultDataConstants.DEFAULT_USER_ICON);
        } else {
            String[] split = memberInfo.getIcon().split(",");
            if(split.length > 1){
                memberInfo.setIcon(split[0]);
            }
        }
        if(StringUtils.isEmpty(memberInfo.getSign())){
            memberInfo.setSign(DefaultDataConstants.DEFAULT_USER_SIGN);
        }
        memberInfo.setIntegration(0L);
        memberInfo.setGrowth(0L);
        memberInfo.setRegisterTime(DateUtils.getNowDate());
        memberInfo.setDelFlag(0L);

        //设置密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(memberInfo.getPassword());
        memberInfo.setPassword(encode);

        return save(memberInfo) ? 1 : 0;
    }

    /**
     * 修改一个用户
     * @author 胡菜鸡
     * @date 2022/5/6 14:51
     */
    @Override
    public int updateMember(MemberInfo memberInfo) {
        if(memberInfo.getNickname() == null || memberInfo.getStuId() == null || memberInfo.getPassword() == null || memberInfo.getPhone() == null){
            throw new ServiceException("缺少部分数据没有传入，请检查传入数据");
        }
        MemberInfo memberDB = baseMapper.selectById(memberInfo.getId());
        //进行数据处理
        if(memberInfo.getStuId().equals(memberDB.getStuId())){
            //如果学号和数据库中数据相同，则无需修改
            memberInfo.setStuId(null);
        } else {
            //不同则需要判断学号是否已存在
            if(checkStuIdUniques(memberInfo.getStuId())){
                throw new LoginException("此学号已存在", ExceptionTypeConstants.STUDENT_ID_EXIST);
            }
        }
        if(StringUtils.isBlank(memberInfo.getPassword())){
            //如果密码是前端设置的空值，则无需修改
            memberInfo.setPassword(null);
        } else {
            //否则需要对密码进行加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String encode = passwordEncoder.encode(memberInfo.getPassword());
            memberInfo.setPassword(encode);
        }
        if(memberInfo.getPhone().equals(memberDB.getPhone())){
            //如果电话号码和数据库中数据相同，则无需修改
            memberInfo.setPhone(null);
        } else {
            //不同则需要判断手机号是否已存在
            if(checkPhoneUniques(memberInfo.getPhone())){
                throw new LoginException("此手机号已存在", ExceptionTypeConstants.PHONE_EXIST);
            }
        }
        return updateById(memberInfo) ? 1 : 0;
    }

    /**
     * 获取个人所有订单以及订单项
     * @author 胡菜鸡
     * @date 2022/4/27 17:20
     */
    private OrderPageResVo getMemberOrders(PersonParamVo personParamVo){
        MemberInfoTo memberInfoTo = MemberInterceptor.threadLocal.get();
        //获取个人的所有订单及对应订单项
        AjaxResult orders = orderFeignService.getOrders(memberInfoTo.getId(), personParamVo);
        OrderPageResVo data = orders.getData("data", new TypeReference<OrderPageResVo>() {});
        if(data == null || data.getOrderResponseVo() == null) return null;
        //数据转化
        List<OrderResponseVo> collect = data.getOrderResponseVo().stream().map(orderResponseVo -> {
            OrderInfoVo order = orderResponseVo.getOrder();
            //转化日期格式
            order.setCreateTimeChina(toChinaDate(order.getCreateTime()));
            //转化订单状态
            order.setStatusChinese(OrderStatusEnum.getByCode(order.getStatus()));
            orderResponseVo.setOrder(order);
            return orderResponseVo;
        }).collect(Collectors.toList());
        data.setOrderResponseVo(collect);
        return data;
    }

    /**
     * 修改日期格式为 年-月-日 时:分:秒
     * @author 胡菜鸡
     * @date 2022/4/27 16:23
     */
    private String toChinaDate(Date date){
        //修改日期格式为中文
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simple.format(date);
    }
}
